
using namespace std;

#include "ConsumidorRespuestas.h"
Socket *conexionSingal;
int socketId1;
int socketId2;

ConsumidorRespuestas::ConsumidorRespuestas(bool atributo) : Thread(atributo){
	this->conexion 	= NULL;
}

ConsumidorRespuestas::~ConsumidorRespuestas() {
	free(this);
}
//Setters
void ConsumidorRespuestas::setConexion(Socket *conexion){
	this->conexion = conexion;
}
void ConsumidorRespuestas::setJugador1(int socketId){
	this->socketIdJugador1 = socketId;
	socketId1 = socketId;
}
void ConsumidorRespuestas::setJugador2(int socketId){
	this->socketIdJugador2 = socketId;
	socketId2 = socketId;
}


//Manejador de señales de interrupcion.
void ConsumidorRespuestas::signalHandler(int signal){
	if(signal == SIGURG){
		//Informo la finalizacion por sysout
		cout << "[INFO] - Se cierra el hilo de respuesta a clientes. "<< endl;
		cout << "[INFO] - Notificando a los usuarios el fin de la partida. " << endl;

		t_accion a;
		a.id_accion = ACC_FIN_PARTIDA;
		a.id_entidad = CONST_CERO;
		a.mov_x = CONST_CERO;
		a.mov_y = CONST_CERO;

		/* La envio a jugador 1 si es que esta conectado, o si no esta conectado pero le quiero avisar que se acaba de desconectar */
		if(Partida::getInstance()->getPartida()->jugador1.conectado)
			conexionSingal->write(((void *)&a), sizeof(a), socketId1);

		/* La envio a jugador 2 si es que esta conectado, o si no esta conectado pero le quiero avisar que se acaba de desconectar */
		if(Partida::getInstance()->getPartida()->jugador2.conectado)
			conexionSingal->write(((void *)&a), sizeof(a), socketId2);

		//Cierro el thread.
		pthread_exit(NULL);
	}
}

void ConsumidorRespuestas::run (){
	/* Me attacho a la señal que envia el server para finalizar. */
	signal(SIGFPE, ConsumidorRespuestas::signalHandler);
	signal(SIGILL, ConsumidorRespuestas::signalHandler);
	signal(SIGURG, ConsumidorRespuestas::signalHandler);
	signal(SIGABRT, ConsumidorRespuestas::signalHandler);
	signal(SIGCLD, ConsumidorRespuestas::signalHandler);
	signal(SIGQUIT, ConsumidorRespuestas::signalHandler);
	signal(SIGIO,  ConsumidorRespuestas::signalHandler);

	/* Mientras el cliente este activo */
	while (Partida::getInstance()->isActivo()) {
		/* Desencolo la respuesta generada */
		t_accion toSend = Partida::getInstance()->desencolarRespuestaJugadores();

		/* La envio a jugador 1 si es que esta conectado, o si no esta conectado pero le quiero avisar que se acaba de desconectar */
		if(Partida::getInstance()->getPartida()->jugador1.conectado || (toSend.id_accion == ACC_SALIR_JUEGO && toSend.id_entidad == CONST_ID_FELIX1))
			if(this->conexion->write(((void *)&toSend), sizeof(toSend), this->socketIdJugador1) == -1){
				cout << "[ERROR] - No se pudo enviar una accion al jugador1. " << toSend.id_accion <<  endl;
				Partida::getInstance()->getPartida()->jugador2.conectado = CONST_FALSE;
				Partida::getInstance()->actualizarJugadorServidorTorneo();
			}

		/* La envio a jugador 2 si es que esta conectado, o si no esta conectado pero le quiero avisar que se acaba de desconectar */
		if(Partida::getInstance()->getPartida()->jugador2.conectado || (toSend.id_accion == ACC_SALIR_JUEGO && toSend.id_entidad == CONST_ID_FELIX2))
			if(this->conexion->write(((void *)&toSend), sizeof(toSend), this->socketIdJugador2) == -1){
				cout << "[ERROR] - No se pudo enviar una accion al jugador2: " << toSend.id_accion << endl;
				Partida::getInstance()->getPartida()->jugador2.conectado = CONST_FALSE;
				Partida::getInstance()->actualizarJugadorServidorTorneo();
			}

		usleep(20000);
	}

	//Informo la finalizacion por sysout
	cout << "[INFO] - Se cierra el hilo de respuesta a clientes. "<< endl;
	cout << "[INFO] - Notificando a los usuarios el fin de la partida. " << endl;

	t_accion a;
	a.id_accion = ACC_FIN_PARTIDA;
	a.id_entidad = CONST_CERO;
	a.mov_x = CONST_CERO;
	a.mov_y = CONST_CERO;

	/* La envio a jugador 1 si es que esta conectado, o si no esta conectado pero le quiero avisar que se acaba de desconectar */
	if(Partida::getInstance()->getPartida()->jugador1.conectado)
		this->conexion->write(((void *)&a), sizeof(a), this->socketIdJugador1);

	/* La envio a jugador 2 si es que esta conectado, o si no esta conectado pero le quiero avisar que se acaba de desconectar */
	if(Partida::getInstance()->getPartida()->jugador2.conectado)
		this->conexion->write(((void *)&a), sizeof(a), this->socketIdJugador2);

	//Cierro el thread.
	pthread_exit(NULL);
}
	
